#pragma once

#include <compl.h>

/* 这种方式可能会造成等待时间比较长? */
// #define COMBINEDIRECT_ENQUEUE

/* 基础对象指针 */
typedef void	apds_t;
typedef byte_t	apdspeff_t;

typedef unsigned int lkflag_t;

/* #ifndef __aarch64__ */
#define APDS_PREFETCH(...)		PREFETCH(__VA_ARGS__)
/* #else
	#define APDS_PREFETCH(...)		
#endif */
/* 4个参数比较合理 */
#ifndef APDSARGS_NR
	#define APDSARGS_NR		4
#endif

#define APDSARGS_PAT			RANGE8(APDSARGS_NR)
#define APDSFUNC_ARGLIST		MAPC(__FUNC_ARGLIST, APDSARGS_PAT)
#define APDSFUNC_ARGUSELIST		MAPC(__FUNC_USEARGLIST, APDSARGS_PAT)

typedef word_t	(apdsfunc_t)(APDSFUNC_ARGLIST);
typedef word_t	apdsret_t;

typedef struct apdsarg
{
	word_t 	arg[APDSARGS_NR];
} apdsarg_t;

/* 用于内部函数声明 */
#define APDSFUTURE_DECL_NOFLAG	\
	apdsarg_t	args;\
	apdsfunc_t	*func;

#define APDSFUTURE_DECL	\
	APDSFUTURE_DECL_NOFLAG\
	lkflag_t	flag;

typedef struct apdsreq
{
	APDSFUTURE_DECL
} apdsfuture_t;

#define __MAP_ARGS(arg)			(word_t)(arg)
#define __APDS_ARGS(arg_name, ...)	word_t __##arg_name [APDSARGS_NR] = { __VA_ARGS__ };  apdsarg_t *arg_name = (apdsarg_t *)__##arg_name; SASSERT(sizeof(__##arg_name) <= sizeof(apdsarg_t));
#define APDS_ARGS(arg_name, ...)	__APDS_ARGS(arg_name, MAPC(__MAP_ARGS, __VA_ARGS__))


#define __APDS_UNROLL_ARGS(num)		args->arg[num]
#define APDS_UNROLL_ARGS(...)		MAPC(__APDS_UNROLL_ARGS, __VA_ARGS__)

SAI word_t apds_args_ret(apdsarg_t *args){
	/* 必须是原子的否则会出错? */
	return atm_ld(&args->arg[0]);
}

SAI void apds_movargs(apdsarg_t *args_to, apdsarg_t *args_from){
	__memcpy(args_to, args_from, sizeof(apdsarg_t));
}

SAI word_t apds_sync_single(apdsfunc_t *func, apdsarg_t *args){
	/* unroll the parameters */
	return func(APDS_UNROLL_ARGS(APDSARGS_PAT));
}

SAI void apds_set_ret(apdsarg_t *args, word_t ret){
	atm_st(&args->arg[0], ret);
}

/* 包含初始化, fetch, wait, sync(fetch + wait), destruct四个接口 */
/* wait需要apds吗? 不应该直接绑定? 但是空间不够啊(参数变成4个就够了)*/
STA_OUFUN(apds)
apds_t* (* const init) (void *ptr, size_t size);	/* 将一段内存初始化为apds对象 */
void* (* const destruct) (apds_t *l);			/* 将apds对象解构为内存 */
apdsfuture_t* (* const fetch) (apds_t *l, apdsfunc_t *pfunc, apdsarg_t *args);	/* 异步fetch, 提前发射请求获得一个future */
apdsret_t (* const wait) (apds_t *l, apdsfuture_t *f);	/* 等待future结果, 这个接口要传l是为了避免依赖从f中获得l导致的流水线阻塞 */
apdsret_t (* const sync) (apds_t *l, apdsfunc_t *pfunc, apdsarg_t *args); /* 同步方式, 直接一次性执行完 */
END_OUFUN(apds)


